`include "define.sv"

module systolic_array_unified (
    input clk,
    input reset,
    input [1:0] matrix_type,
    input [`DATA_WIDTH-1:0] a_in [0:31],
    input [`DATA_WIDTH-1:0] b_in [0:31],
    input [`DATA_WIDTH-1:0] c_in [0:15][0:15],
    input [1:0] data_type,
    input mix_precision,
    output [`DATA_WIDTH-1:0] c_out [0:15][0:15],
    input [31:0] a_fifo_empty, // A FIFO空信号
    input [31:0] b_fifo_empty,  // B FIFO空信号
    input c_wr_en [0:15][0:15],
    output calc_done [0:15][0:15],
    input pe_reset               // PE内部复位信号
);

    // PE间连接信号
    wire [`DATA_WIDTH-1:0] pe_a_out [0:31][0:15];
    wire [`DATA_WIDTH-1:0] pe_b_out [0:15][0:31];
    wire mult_en [0:15][0:15];
    reg [`DATA_WIDTH-1:0] a [0:31][0:31];
    reg [`DATA_WIDTH-1:0] b [0:31][0:31];
    //reg [`DATA_WIDTH-1:0] c [0:31][0:31];
    //reg c_add_en [0:31][0:31];
    reg result_valid [0:15][0:15];  //结果有效信号
    reg mult_en_out [0:15][0:15];


    // PE阵列实例化
    genvar i, j;
    generate
        for(i=0; i<16; i=i+1) begin:row
            for(j=0; j<16; j=j+1) begin:col
                // 实例化处理单元pe
                pe u_pe(
                   .clk(clk),
                   .reset(reset),
                   .a_in(a[i][j]),
                   .b_in(b[i][j]),
                   .c_in(c_in[i][j]),
                   .data_type(data_type),
                   .mix_precision(mix_precision),
                   .mult_en(mult_en[i][j]),    
                   .c_add_en(c_wr_en[i][j]),
                   .a_out(pe_a_out[i][j]),
                   .b_out(pe_b_out[i][j]),
                   .c_out(c_out[i][j]),
                   .add_valid_o(result_valid[i][j]),  // 连接adder_valid信号
                   .calc_done(calc_done[i][j]),   // 结果输出有效信号
                   .mult_en_out(mult_en_out[i][j]),
                   .pe_reset(pe_reset)            // 连接PE内部复位信号
                );
            end
        end
    endgenerate
/*
    // PE阵列实例化
    genvar i, j;
    generate
        for(i=0; i<16; i=i+1) begin:row
            for(j=0; j<16; j=j+1) begin:col
                // 实例化处理单元pe（外圈pe阵列）
                pe u_pe(
                   .clk(clk),
                   .reset(reset),
                   .a_in(a[i][j]),
                   .b_in(b[i][j]),
                   .c_in(c[i][j]),
                   .data_type(data_type),
                   .mix_precision(mix_precision),
                   .mult_en(mult_en[i][j]),    
                   .c_add_en(c_add_en[i][j]),
                   .a_out(pe_a_out[i][j]),
                   .b_out(pe_b_out[i][j]),
                   .c_out(c_out[i][j]),
                   .add_valid_o(result_valid[i][j])  // 连接adder_valid信号
                   //.result_valid(result_valid[i][j])   // 结果输出有效信号
                );
            end
        end
        for(i=1; i<16; i=i+1) begin:row
            for(j=1; j<16; j=j+1) begin:col
                // 实例化处理单元pe（内圈pe阵列）
                pe u_pe(
                   .clk(clk),
                   .reset(reset),
                   .a_in(a[i][j]),
                   .b_in(b[i][j]),
                   .c_in(c[i][j]),
                   .data_type(data_type),
                   .mix_precision(mix_precision),
                   .mult_en(mult_en[i][j]),    
                   .c_add_en(c_add_en[i][j]),
                   .a_out(pe_a_out[i][j]),
                   .b_out(pe_b_out[i][j]),
                   .c_out(c_out[i][j]),
                   .add_valid_o(result_valid[i][j])  // 连接adder_valid信号
                   //.result_valid(result_valid[i][j])   // 结果输出有效信号
                );
            end
        end
    endgenerate
*/
    // 实例化矩阵路由器
    matrix_router u_matrix_router (
       .clk(clk),
       .reset(reset),
       .matrix_type(matrix_type),
       .a_in(a_in),
       .b_in(b_in),
       .pe_a_out(pe_a_out),
       .pe_b_out(pe_b_out),
       .pe_mult_en_out(mult_en_out),
       //.c_in(c_in),
       .a(a),
       .b(b),
       //.c(c),
       //.c_add_en(c_add_en),
       .a_fifo_empty(a_fifo_empty),
       .b_fifo_empty(b_fifo_empty),
       //.c_fifo_empty(c_fifo_empty),
       .mult_en(mult_en)
    );

endmodule

